﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace UDS.Management.SMS
{
    /// <summary>
    /// Defines some helper functions for SMS Sender.
    /// </summary>
    internal static class SmsUtility
    {
        internal static string[] SplitSMS(string msg)
        {
            if (string.IsNullOrEmpty(msg))
            {
                throw new ArgumentNullException("msg");
            }

            const int MaxLengthPerEnglishSMS = 140;
            const int MaxLengthPerChineseSMS = 70;

            if (msg.Length <= MaxLengthPerChineseSMS)
            {
                return new string[] { msg };
            }

            List<string> list = new List<string>();

            int start = 0;
            while (start < msg.Length)
            {
                // Find the position of next Chinese char.
                int chnPos = start;
                do
                {
                    char ch = msg[chnPos];
                    if (ch > 0xff)
                    {
                        break;
                    }

                    chnPos++;
                }
                while (chnPos < msg.Length);

                // Found a Chinese char.
                int len = chnPos - start;
                if (len > 0)
                {
                    // Firstly, we'll read English segments with 140 chars.
                    while (len >= MaxLengthPerEnglishSMS)
                    {
                        list.Add(msg.Substring(start, MaxLengthPerEnglishSMS));
                        start += MaxLengthPerEnglishSMS;
                        len -= MaxLengthPerEnglishSMS;
                    }
                }
                else
                {
                    // The first character is a Chinese one.
                    len = 1;
                }

                // Add messages with Chinese characters.
                len = ((len + MaxLengthPerChineseSMS - 1) / MaxLengthPerChineseSMS) * MaxLengthPerChineseSMS; // Round up to 70 chars.
                len = Math.Min(len, msg.Length - start);

                while (len >= MaxLengthPerChineseSMS)
                {
                    list.Add(msg.Substring(start, MaxLengthPerChineseSMS));
                    start += MaxLengthPerChineseSMS;
                    len -= MaxLengthPerChineseSMS;
                }
                if (len > 0)
                {
                    list.Add(msg.Substring(start, len));
                    start += len;
                }
            }

            return list.ToArray();
        }

        internal static string MobileNum_to_pdu(string number)
        {
            if (string.IsNullOrEmpty(number))
                throw new ArgumentNullException("number");

            // Remove unncessary characters to only keep digital ones.
            number = Regex.Replace(number, @"[^\d]", string.Empty);
            if (number.Length == 13 || number.Length == 11)
            {
                if (number.Length == 11)
                    number = "86" + number;

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 13; i += 2)
                {
                    char ch = number[i];
                    if (i == 12)
                    {
                        sb.Append('F');
                        sb.Append(ch);
                    }
                    else
                    {
                        sb.Append(number[i + 1]);
                        sb.Append(ch);
                    }
                }
                return sb.ToString();
            }

            throw new ArgumentException(string.Format("Invalid phone number: {0}", number), "number");
        }

        internal static string Smsg2Pdu(string msg)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(msg);
            StringBuilder sb = new StringBuilder(bytes.Length * 2);

            int len = bytes.Length;
            bool last = false;
            if ((len & 1) == 1)
            {
                len -= 1;
                last = true;
            }
            for (int i = 0; i < len; i += 2)
            {
                sb.Append(bytes[i + 1].ToString("X2"));
                sb.Append(bytes[i].ToString("X2"));
            }

            if (last)
            {
                sb.Append(bytes[len].ToString("X2"));
            }

            return sb.ToString();
        }

        internal static string Sms2Pdu(string smsCenter, string phone, string msg)
        {
            int msgLen = msg.Length * 2;
            string msgLenStr = msgLen.ToString("X2");

            StringBuilder sb = new StringBuilder();
            sb.Append("0891");
            sb.Append(MobileNum_to_pdu(smsCenter));
            sb.Append("11000D91");
            sb.Append(MobileNum_to_pdu(phone));
            sb.Append("000800");
            sb.AppendFormat("{0:X2}", msg.Length * 2);
            sb.Append(Smsg2Pdu(msg));
            return sb.ToString();
        }
    }
}
